1 /*
2 * Scope: a generic MVC framework.
3 * Copyright (c) 2000-2002, The Scope team
4 * All rights reserved.
5 *
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * Neither the name "Scope" nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 *
36 * $Id: SetModel.java,v 1.9 2002/09/12 10:51:03 ludovicc Exp $
37 */
38 package org.scopemvc.model.collection;
39
40
41 import java.util.Collection;
42 import java.util.HashSet;
43 import java.util.Iterator;
44 import java.util.Set;
45 import org.apache.commons.logging.Log;
46 import org.apache.commons.logging.LogFactory;
47 import org.scopemvc.core.ModelChangeEvent;
48 import org.scopemvc.core.ModelChangeEventSource;
49 import org.scopemvc.core.Selector;
50 import org.scopemvc.util.Debug;
51 import org.scopemvc.model.basic.BasicModel;
52
53 /***
54 * <P>
55 *
56 * A BasicModel wrapper for an <CODE>Set</CODE> that can propagate changes to
57 * contained Models up the Model hierarchy. The set itself is exposed via the
58 * "set" property, however, changes to this underlying set must be made through
59 * this class's public API in order to maintain the event propagation. </P> <P>
60 *
61 * By default SetModel registers itself as a listener to Models that are added
62 * to the list and deregisters when those Models are removed. This behaviour can
63 * be changed at creation so that ModelChangeEvent propagation from contained
64 * models is disabled. </P>
65 *
66 * @author <A HREF="mailto:smeyfroi@users.sourceforge.net">Steve Meyfroidt</A>
67 * @created 05 September 2002
68 * @version $Revision: 1.9 $
69 */
70 public class SetModel extends BasicModel implements Set {
71
72 /***
73 * TODO: describe of the Field
74 */
75 public static final Selector SET = Selector.fromString("set");
76
77 // ----------------- for debug -----------------------
78
79 /***
80 * TODO: describe of the Field
81 */
82 protected static final String TO_STRING_SEPARATOR = ", ";
83 /***
84 * TODO: describe of the Field
85 */
86 protected static final int TO_STRING_SEPARATOR_LENGTH = TO_STRING_SEPARATOR.length();
87
88 private static final Log LOG = LogFactory.getLog(ListModel.class);
89
90 /***
91 * TODO: describe of the Field
92 */
93 protected Set contents;
94
95 /***
96 * TODO: describe of the Field
97 */
98 protected boolean propagateModelChanges;
99
100
101 /***
102 * Constructor for the SetModel object
103 */
104 public SetModel() {
105 this(true, new HashSet());
106 }
107
108
109 /***
110 * Constructor for the SetModel object
111 *
112 * @param inSet TODO: Describe the Parameter
113 */
114 public SetModel(Set inSet) {
115 this(true, inSet);
116 }
117
118
119 /***
120 * Constructor for the SetModel object
121 *
122 * @param inPropagateModelChanges TODO: Describe the Parameter
123 */
124 public SetModel(boolean inPropagateModelChanges) {
125 propagateModelChanges = inPropagateModelChanges;
126 }
127
128
129 /***
130 * Constructor for the SetModel object
131 *
132 * @param inPropagateModelChanges TODO: Describe the Parameter
133 * @param inSet TODO: Describe the Parameter
134 */
135 public SetModel(boolean inPropagateModelChanges, Set inSet) {
136 this(inPropagateModelChanges);
137 setSet(inSet);
138 }
139
140
141 /***
142 * Gets the set
143 *
144 * @return The set value
145 */
146 public Set getSet() {
147 return contents;
148 }
149
150
151 /***
152 * Gets the size
153 *
154 * @return The size value
155 */
156 public int getSize() {
157 if (contents == null) {
158 return 0;
159 }
160 return contents.size();
161 }
162
163
164 /***
165 * Gets the empty
166 *
167 * @return The empty value
168 */
169 public boolean isEmpty() {
170 return contents.isEmpty();
171 }
172
173
174 /***
175 * Set contents to the passed Object list and fire a ModelChangeEvent.
176 *
177 * @param inContents The new set value
178 */
179 public void setSet(Set inContents) {
180
181 if (propagateModelChanges) {
182 // Clear up old list if it contained any Models
183 if (contents != null) {
184 for (Iterator i = contents.iterator(); i.hasNext(); ) {
185 Object o = i.next();
186 if (o instanceof ModelChangeEventSource) {
187 ((ModelChangeEventSource) o).removeModelChangeListener(this);
188 }
189 }
190 }
191 }
192
193 contents = inContents;
194
195 if (propagateModelChanges) {
196 // Register as listener to any Models in the new list
197 if (contents != null) {
198 for (Iterator i = contents.iterator(); i.hasNext(); ) {
199 Object o = i.next();
200 if (o instanceof ModelChangeEventSource) {
201 ((ModelChangeEventSource) o).addModelChangeListener(this);
202 }
203 }
204 }
205 }
206
207 fireModelChange(ModelChangeEvent.VALUE_CHANGED, SET);
208 }
209
210
211 /***
212 * TODO: document the method
213 *
214 * @param inEvent TODO: Describe the Parameter
215 */
216 public void modelChanged(ModelChangeEvent inEvent) {
217 if (Debug.ON) {
218 Debug.assertTrue(inEvent != null);
219 }
220 if (LOG.isDebugEnabled()) {
221 LOG.debug("modelChanged: " + inEvent);
222 }
223
224 // Just say that the set changed somehow: can't select elements of a set
225 fireModelChange(VALUE_CHANGED, null);
226 }
227
228 /***
229 * TODO: document the method
230 *
231 * @return TODO: Describe the Return Value
232 */
233 public String toString() {
234
235 if (contents == null) {
236 return "";
237 }
238
239 StringBuffer result = new StringBuffer("(");
240
241 for (Iterator i = contents.iterator(); i.hasNext(); ) {
242 Object o = i.next();
243 result.append(o == null ? "<null>" : o.toString());
244 result.append(TO_STRING_SEPARATOR);
245 }
246
247 if (contents.size() > 0) {
248 result.setLength(result.length() - TO_STRING_SEPARATOR_LENGTH);
249 }
250 result.append(')');
251
252 return result.toString();
253 }
254
255
256 // -------------------------- implement Set ------------------------------
257
258 /***
259 * TODO: document the method
260 *
261 * @return TODO: Describe the Return Value
262 */
263 public int size() {
264 return contents.size();
265 }
266
267
268 /***
269 * TODO: document the method
270 *
271 * @param arg0 TODO: Describe the Parameter
272 * @return TODO: Describe the Return Value
273 */
274 public boolean contains(Object arg0) {
275 return contents.contains(arg0);
276 }
277
278
279 /***
280 * TODO: document the method
281 *
282 * @return TODO: Describe the Return Value
283 */
284 public Iterator iterator() {
285 return contents.iterator();
286 }
287
288
289 /***
290 * TODO: document the method
291 *
292 * @return TODO: Describe the Return Value
293 */
294 public Object[] toArray() {
295 return contents.toArray();
296 }
297
298
299 /***
300 * TODO: document the method
301 *
302 * @param arg0 TODO: Describe the Parameter
303 * @return TODO: Describe the Return Value
304 */
305 public Object[] toArray(Object[] arg0) {
306 return contents.toArray(arg0);
307 }
308
309
310 /***
311 * TODO: document the method
312 *
313 * @param arg0 TODO: Describe the Parameter
314 * @return TODO: Describe the Return Value
315 */
316 public boolean containsAll(Collection arg0) {
317 return contents.containsAll(arg0);
318 }
319
320
321 /***
322 * TODO: document the method
323 *
324 * @param o TODO: Describe the Parameter
325 * @return TODO: Describe the Return Value
326 */
327 public boolean add(Object o) {
328 if (LOG.isDebugEnabled()) {
329 LOG.debug("add: " + o);
330 }
331 if (!contents.add(o)) {
332 return false;
333 }
334
335 if (propagateModelChanges && o instanceof ModelChangeEventSource) {
336 ((ModelChangeEventSource) o).addModelChangeListener(this);
337 }
338 fireModelChange(VALUE_ADDED, null);
339 return true;
340 }
341
342 /***
343 * TODO: document the method
344 *
345 * @param o TODO: Describe the Parameter
346 * @return TODO: Describe the Return Value
347 */
348 public boolean remove(Object o) {
349 if (LOG.isDebugEnabled()) {
350 LOG.debug("remove: " + o);
351 }
352 if (!contents.remove(o)) {
353 return false;
354 }
355
356 if (propagateModelChanges && o instanceof ModelChangeEventSource) {
357 ((ModelChangeEventSource) o).removeModelChangeListener(this);
358 }
359 fireModelChange(VALUE_REMOVED, null);
360 return true;
361 }
362
363
364 /***
365 * Adds an element to the All attribute of the SetModel object
366 *
367 * @param c The element to be added to the All attribute
368 * @return TODO: Describe the Return Value
369 */
370 public boolean addAll(Collection c) {
371 boolean result = false;
372 makeActive(false);
373 try {
374 for (Iterator i = c.iterator(); i.hasNext(); ) {
375 result = result | add(i.next());
376 }
377 } finally {
378 makeActive(true);
379 }
380 fireModelChange(VALUE_CHANGED, null);
381 return result;
382 }
383
384
385 /***
386 * TODO: document the method
387 *
388 * @param c TODO: Describe the Parameter
389 * @return TODO: Describe the Return Value
390 */
391 public boolean retainAll(Collection c) {
392 Set original = new HashSet(contents);
393 boolean result = false;
394 makeActive(false);
395 try {
396 for (Iterator i = original.iterator(); i.hasNext(); ) {
397 Object o = i.next();
398 if (!c.contains(o)) {
399 remove(o);
400 result = true;
401 }
402 }
403 } finally {
404 makeActive(true);
405 }
406 fireModelChange(VALUE_CHANGED, null);
407 return result;
408 }
409
410
411 /***
412 * TODO: document the method
413 *
414 * @param c TODO: Describe the Parameter
415 * @return TODO: Describe the Return Value
416 */
417 public boolean removeAll(Collection c) {
418 boolean result = false;
419 makeActive(false);
420 try {
421 for (Iterator i = c.iterator(); i.hasNext(); ) {
422 result = result | remove(i.next());
423 }
424 } finally {
425 makeActive(true);
426 }
427 fireModelChange(VALUE_CHANGED, null);
428 return result;
429 }
430
431
432 /***
433 * TODO: document the method
434 */
435 public void clear() {
436 makeActive(false);
437 try {
438 if (propagateModelChanges) {
439 for (Iterator i = contents.iterator(); i.hasNext(); ) {
440 Object o = i.next();
441 if (o instanceof ModelChangeEventSource) {
442 ((ModelChangeEventSource) o).removeModelChangeListener(this);
443 }
444 }
445 }
446 contents.clear();
447 } finally {
448 makeActive(true);
449 }
450 fireModelChange(VALUE_CHANGED, null);
451 }
452
453
454 /***
455 * TODO: document the method
456 *
457 * @param o TODO: Describe the Parameter
458 * @return TODO: Describe the Return Value
459 */
460 public boolean equals(Object o) {
461 return contents.equals(o);
462 }
463
464
465 /***
466 * TODO: document the method
467 *
468 * @return TODO: Describe the Return Value
469 */
470 public int hashCode() {
471 return contents.hashCode();
472 }
473 }
This page was automatically generated by Maven